package com.gmics.unifiq;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.media.ExifInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.gmics.android.R;
import com.samsung.samm.common.SObject;
import com.samsung.samm.common.SObjectImage;
import com.samsung.samm.common.SObjectStroke;
import com.samsung.sdraw.AbstractSettingView;
import com.samsung.sdraw.CanvasView;
import com.samsung.sdraw.SettingView;
import com.samsung.spensdk.SCanvasView;
import com.samsung.spensdk.applistener.HistoryUpdateListener;
import com.samsung.spensdk.applistener.SCanvasInitializeListener;
import com.samsung.spensdk.applistener.SObjectUpdateListener;
import com.samsung.spensdk.applistener.SettingStrokeChangeListener;

public class DrawActivity extends Activity {
	private static final int GALLERY_REQUEST_CODE = 888;
	private static final Bitmap.CompressFormat COMPRESS_FORMAT = Bitmap.CompressFormat.PNG;
	private static final int COMPRESS_QUALITY = 100;
	private static final String SAVED_CANVAS_FILE_NAME = "caricature.png";
	private static final String IMAGE_SCALED_TO_BACKGROUND = "isBackground";
	private ProgressDialog mProgressDialog;
	private static SCanvasView sCanvasView;
	private SettingView mSettingView;
	private File mBitmapFile;
	private Button mBackButton;
	private Button mPencilButton;
	private Button mEraserButton;
	private Button mZoomButton;
	private Button mImageButton;
	private Button mTextButton;
	private Button mUndoButton;
	private Button mRedoButton;
	private Button mPlayButton;
	private Button mSaveButton;
	private Button mCurrentModeButton;
	private boolean mUnsavedChanges;
	private boolean mIsRestoredInstance = false;
	private boolean mIsSavingCanvas;
	private boolean mIsBackgroundSelected;

	@Override
	public void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.draw);
		initCanvas();
		initViews();
		if (savedInstanceState != null) {
			mIsRestoredInstance = true;
		}
	}

	/**
	 * Initializes the canvas object.
	 */
	private void initCanvas() {
		sCanvasView = (SCanvasView) findViewById(R.id.canvas_view);
		sCanvasView.setSCanvasInitializeListener(mSCanvasInitializeListener);
		sCanvasView.setSObjectUpdateListener(mSObjectUpdateListener);
		mSettingView = createSettingsView();
		RelativeLayout canvasContainer = (RelativeLayout) findViewById(R.id.canvas_container);
		sCanvasView.setSettingView(canvasContainer, mSettingView, true);
		sCanvasView
				.setSettingStrokeChangeListener(mSettingStrokeChangeListener);
		sCanvasView.setHistoryUpdateListener(mHistoryUpdateListener);
		sCanvasView.setOnTouchListener(mTouchListener);
	}

	/**
	 * Listener for SCanvasView events.
	 */
	private final SCanvasInitializeListener mSCanvasInitializeListener = new SCanvasInitializeListener() {
		@Override
		public void onInitialized() {
			if (mIsRestoredInstance) {
				mBitmapFile = getSavedCanvasFile();
			} else {
				mBitmapFile = (File) getIntent().getSerializableExtra(
						GroupDetail.PICTURE_FILE_ID);
			}
			new BitmapLoader().execute();
		}
	};

	/**
	 * Listener for SObject events.
	 */
	private final SObjectUpdateListener mSObjectUpdateListener = new SObjectUpdateListener() {
		@Override
		public void onSObjectChanged(SObject sObject, boolean byUndo,
				boolean byRedo) {
		}

		@Override
		public void onSObjectDeleted(SObject sObject, boolean byUndo,
				boolean byRedo, boolean bFreeMemory) {
		}

		@Override
		public void onSObjectInserted(SObject sObject, boolean byUndo,
				boolean byRedo) {
		}

		@Override
		public void onSObjectSelected(SObject sObject, boolean bSelected) {
			if (sObject.getBooleanExtra(IMAGE_SCALED_TO_BACKGROUND, false)) {
				mIsBackgroundSelected = bSelected;
			} else {
				mIsBackgroundSelected = false;
			}
		}

		@Override
		public boolean onSObjectStrokeInserting(SObjectStroke sObjectStroke) {
			return false;
		}

		@Override
		public void onSObjectClearAll(boolean arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onSObjectDeleted(SObject arg0, boolean arg1, boolean arg2,
				boolean arg3, boolean arg4) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onSObjectInserted(SObject arg0, boolean arg1, boolean arg2,
				boolean arg3) {
			// TODO Auto-generated method stub

		}
	};

	@Override
	public void onBackPressed() {
		if (mUnsavedChanges) {
			openSaveDialog();
		} else {
			DrawActivity.this.finish();
		}
	}

	/**
	 * Creates the setting view object in the canvas container of the current
	 * layout.
	 * 
	 * @return Created SettingView object
	 */
	private SettingView createSettingsView() {
		RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
				ViewGroup.LayoutParams.WRAP_CONTENT,
				ViewGroup.LayoutParams.WRAP_CONTENT);
		lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
		lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
		SettingView sv = new SettingView(this);
		sv.setLayoutParams(lp);
		return sv;
	}

	/**
	 * Listener for changing the canvas operations stack.
	 */
	private final HistoryUpdateListener mHistoryUpdateListener = new HistoryUpdateListener() {
		@Override
		public void onHistoryChanged(final boolean undoable,
				final boolean redoable) {
			updateButtonsState();
			mUnsavedChanges = true;
		}
	};

	/**
	 * Listener for handling touch events (especially in zoom mode).
	 */
	private final View.OnTouchListener mTouchListener = new View.OnTouchListener() {
		float lastX = -1;
		float lastY = -1;
		boolean lastActionUp = false;

		@Override
		public boolean onTouch(final View v, final MotionEvent e) {
			if (mCurrentModeButton == null) {
				return true;
			}

			if (mZoomButton.equals(mCurrentModeButton)
					&& e.getPointerCount() == 1) {
				if (!lastActionUp && e.getAction() != MotionEvent.ACTION_UP) {
					sCanvasView.panBy(e.getX() - lastX, e.getY() - lastY);
				}
				if (e.getAction() == MotionEvent.ACTION_UP) {
					lastActionUp = true;
				} else {
					lastActionUp = false;
					lastX = e.getX();
					lastY = e.getY();
				}
				return true;
			}

			if (mIsBackgroundSelected) {
				updateButtonsState(); // switches back to proper mode when
										// background was selected
				return true; // prevents from selecting background image
			}

			return false;
		}
	};

	/**
	 * Listener for changing pen/eraser settings.
	 */
	private final SettingStrokeChangeListener mSettingStrokeChangeListener = new SettingStrokeChangeListener() {

		@Override
		public void onClearAll(boolean bClearAllCompleted) {
			if (bClearAllCompleted) {
				new BitmapLoader().execute();
			}
		}

		@Override
		public void onEraserWidthChanged(int eraserWidth) {
		}

		@Override
		public void onStrokeAlphaChanged(int strokeAlpha) {
		}

		@Override
		public void onStrokeColorChanged(int strokeColor) {
		}

		@Override
		public void onStrokeStyleChanged(int strokeStyle) {
		}

		@Override
		public void onStrokeWidthChanged(int strokeWidth) {
		}

		@Override
		public void onBeautifyPenStyleParameterBeautifyStyleIDChanged(int arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onBeautifyPenStyleParameterCursiveChanged(int arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onBeautifyPenStyleParameterDummyChanged(int arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onBeautifyPenStyleParameterFillStyleChanged(int arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onBeautifyPenStyleParameterModulationChanged(int arg0) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onBeautifyPenStyleParameterSustenanceChanged(int arg0) {
			// TODO Auto-generated method stub

		}
	};

	/**
	 * Initializes all visible views.
	 */
	private void initViews() {
		TextView appNameText = (TextView) findViewById(R.id.app_name_text);
		appNameText.setTypeface(Typeface.createFromAsset(getAssets(),
				"fonts/Roboto-Regular.ttf"));
		mBackButton = (Button) findViewById(R.id.back_button);
		mBackButton.setOnClickListener(mBackButtonListener);
		mPencilButton = (Button) findViewById(R.id.pencil_button);
		mPencilButton.setOnClickListener(mPencilButtonListener);
		mEraserButton = (Button) findViewById(R.id.eraser_button);
		mEraserButton.setOnClickListener(mEraserButtonListener);
		mZoomButton = (Button) findViewById(R.id.zoom_button);
		mZoomButton.setOnClickListener(mZoomButtonListener);
		mImageButton = (Button) findViewById(R.id.image_button);
		mImageButton.setOnClickListener(mImageButtonListener);
		mTextButton = (Button) findViewById(R.id.text_button);
		mTextButton.setOnClickListener(mTextButtonListener);
		mUndoButton = (Button) findViewById(R.id.undo_button);
		mUndoButton.setOnClickListener(mUndoButtonListener);
		mRedoButton = (Button) findViewById(R.id.redo_button);
		mRedoButton.setOnClickListener(mRedoButtonListener);
		mPlayButton = (Button) findViewById(R.id.play_button);
		mPlayButton.setOnClickListener(mPlayButtonListener);
		mSaveButton = (Button) findViewById(R.id.save_button);
		mSaveButton.setOnClickListener(mSaveButtonListener);
	}

	/**
	 * Listener for clicking "back" button.
	 */
	private final OnClickListener mBackButtonListener = new OnClickListener() {
		@Override
		public void onClick(final View v) {
			if (mUnsavedChanges) {
				openSaveDialog();
			} else {
				DrawActivity.this.finish();
			}
			mCurrentModeButton = mBackButton;
			updateButtonsState();
		}
	};

	/**
	 * Listener for clicking "pencil" button.
	 */
	private final OnClickListener mPencilButtonListener = new OnClickListener() {
		@Override
		public void onClick(final View v) {
			if (mSettingView.isShown(AbstractSettingView.PEN_SETTING_VIEW)) {
				mSettingView.closeView();
			} else {
				mSettingView.showView(AbstractSettingView.PEN_SETTING_VIEW);
			}
			mCurrentModeButton = mPencilButton;
			updateButtonsState();
		}
	};

	/**
	 * Listener for clicking "eraser" button.
	 */
	private final OnClickListener mEraserButtonListener = new OnClickListener() {
		@Override
		public void onClick(final View v) {
			if (mSettingView.isShown(AbstractSettingView.ERASER_SETTING_VIEW)) {
				mSettingView.closeView();
			} else {
				mSettingView.showView(AbstractSettingView.ERASER_SETTING_VIEW);
			}
			mCurrentModeButton = mEraserButton;
			updateButtonsState();
		}
	};

	/**
	 * Listener for clicking "zoom" button.
	 */
	private final OnClickListener mZoomButtonListener = new OnClickListener() {
		@Override
		public void onClick(final View v) {
			mCurrentModeButton = mZoomButton;
			updateButtonsState();
		}
	};

	/**
	 * Listener for clicking "image" button.
	 */
	private final OnClickListener mImageButtonListener = new OnClickListener() {
		@Override
		public void onClick(final View v) {
			Intent intent = new Intent(DrawActivity.this, GalleryActivity.class);
			startActivityForResult(intent, GALLERY_REQUEST_CODE);
			mCurrentModeButton = mImageButton;
			updateButtonsState();
		}
	};

	/**
	 * Listener for clicking "text" button.
	 */
	private final OnClickListener mTextButtonListener = new OnClickListener() {
		@Override
		public void onClick(final View v) {
			mCurrentModeButton = mTextButton;
			updateButtonsState();
		}
	};

	/**
	 * Listener for clicking "undo" button.
	 */
	private final OnClickListener mUndoButtonListener = new OnClickListener() {
		@Override
		public void onClick(final View v) {
			sCanvasView.undo();
			updateButtonsState();
		}
	};

	/**
	 * Listener for clicking "redo" button.
	 */
	private final OnClickListener mRedoButtonListener = new OnClickListener() {
		@Override
		public void onClick(final View v) {
			sCanvasView.redo();
			updateButtonsState();
		}
	};

	/**
	 * Listener for clicking "play" button.
	 */
	private final OnClickListener mPlayButtonListener = new OnClickListener() {
		@Override
		public void onClick(final View v) {
			play();
			mCurrentModeButton = mPlayButton;
			updateButtonsState();
		}
	};

	/**
	 * Listener for clicking "save" button.
	 */
	private final OnClickListener mSaveButtonListener = new OnClickListener() {
		@Override
		public void onClick(final View v) {
			save();
			mCurrentModeButton = mSaveButton;
			updateButtonsState();
		}
	};

	/**
	 * Opens a dialog when the user tries to quit with unsaved changes.
	 */
	private void openSaveDialog() {
		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(R.string.unsaved_changes)
				.setCancelable(true)
				.setPositiveButton(R.string.save,
						new DialogInterface.OnClickListener() {
							@Override
							public void onClick(final DialogInterface dialog,
									final int id) {
								save();
							}
						})
				.setNegativeButton(R.string.exit,
						new DialogInterface.OnClickListener() {
							@Override
							public void onClick(final DialogInterface dialog,
									final int id) {
								finish();
							}
						});
		builder.create().show();
	}

	/**
	 * Starts an activity for playing an animation.
	 */
	private void play() {
		Intent intent = new Intent(DrawActivity.this, AnimationActivity.class);
		intent.putExtra(AnimationActivity.SAMM_DATA_KEY,
				sCanvasView.saveSAMMData());
		startActivity(intent);
	}

	/**
	 * Starts an activity for saving the picture.
	 */
	private void save() {
		mUnsavedChanges = false;
		Intent intent = new Intent(DrawActivity.this, SaveActivity.class);
		startActivityForResult(intent, 0);
	}

	/**
	 * Updates all buttons for current application state.
	 */
	private void updateButtonsState() {
		updateUndoRedoState();
		setClickedButton();
	}

	/**
	 * Updates "undo" and "redo" buttons according to the current canvas
	 * operations stack.
	 */
	private void updateUndoRedoState() {
		mUndoButton.setClickable(sCanvasView.isUndoable());
		mRedoButton.setClickable(sCanvasView.isRedoable());

		if (mUndoButton.isClickable()) {
			mUndoButton.setBackgroundResource(R.drawable.undo_btn);
		} else {
			mUndoButton.setBackgroundResource(R.drawable.undo_btn_pressed);
		}

		if (mRedoButton.isClickable()) {
			mRedoButton.setBackgroundResource(R.drawable.redo_btn);
		} else {
			mRedoButton.setBackgroundResource(R.drawable.redo_btn_pressed);
		}
	}

	/**
	 * Sets clicked button according to the current drawing mode.
	 */
	private void setClickedButton() {
		resetClickedButton();

		if (mCurrentModeButton != null) {
			if (mCurrentModeButton.equals(mBackButton)) {
				mBackButton.setBackgroundResource(R.drawable.back_btn_pressed);
				sCanvasView.changeModeTo(CanvasView.SELECT_MODE);
			} else if (mCurrentModeButton.equals(mPencilButton)) {
				mPencilButton
						.setBackgroundResource(R.drawable.pencil_btn_pressed);
				sCanvasView.changeModeTo(CanvasView.PEN_MODE);
			} else if (mCurrentModeButton.equals(mEraserButton)) {
				mEraserButton
						.setBackgroundResource(R.drawable.eraser_btn_pressed);
				sCanvasView.changeModeTo(CanvasView.ERASER_MODE);
			} else if (mCurrentModeButton.equals(mZoomButton)) {
				mZoomButton.setBackgroundResource(R.drawable.zoom_btn_pressed);
				sCanvasView.changeModeTo(CanvasView.SELECT_MODE);
			} else if (mCurrentModeButton.equals(mImageButton)) {
				mImageButton
						.setBackgroundResource(R.drawable.image_btn_pressed);
				sCanvasView.changeModeTo(CanvasView.SELECT_MODE);
			} else if (mCurrentModeButton.equals(mTextButton)) {
				mTextButton.setBackgroundResource(R.drawable.text_btn_pressed);
				sCanvasView.changeModeTo(CanvasView.TEXT_MODE);
			} else if (mCurrentModeButton.equals(mPlayButton)) {
				mPlayButton.setBackgroundResource(R.drawable.play_btn_pressed);
				sCanvasView.changeModeTo(CanvasView.SELECT_MODE);
			} else if (mCurrentModeButton.equals(mSaveButton)) {
				mSaveButton.setBackgroundResource(R.drawable.save_btn_pressed);
				sCanvasView.changeModeTo(CanvasView.SELECT_MODE);
			} else {
				sCanvasView.changeModeTo(CanvasView.SELECT_MODE);
			}
		} else {
			sCanvasView.changeModeTo(CanvasView.SELECT_MODE);
		}
	}

	/**
	 * Sets all buttons as not clicked.
	 */
	private void resetClickedButton() {
		mBackButton.setBackgroundResource(R.drawable.back_btn);
		mPencilButton.setBackgroundResource(R.drawable.pencil_btn);
		mEraserButton.setBackgroundResource(R.drawable.eraser_btn);
		mZoomButton.setBackgroundResource(R.drawable.zoom_btn);
		mImageButton.setBackgroundResource(R.drawable.image_btn);
		mTextButton.setBackgroundResource(R.drawable.text_btn);
		mPlayButton.setBackgroundResource(R.drawable.play_btn);
		mSaveButton.setBackgroundResource(R.drawable.save_btn);
	}

	/**
	 * Background task responsible for loading a bitmap from file as a
	 * background.
	 */
	private class BitmapLoader extends AsyncTask<Void, Void, Void> {
		@Override
		protected void onPreExecute() {
			mProgressDialog = ProgressDialog.show(DrawActivity.this,
					getString(R.string.please_wait),
					getString(R.string.loading_bitmap), true, false);
		}

		@Override
		protected Void doInBackground(final Void... params) {
			try {
				Bitmap bitmap = loadBitmapFromFile(mBitmapFile);
				if (bitmap != null) {
					final SObjectImage image = getImageFromBitmap(bitmap, true,
							true);
					bitmap.recycle();
					runOnUiThread(new Runnable() {
						@Override
						public void run() {
							sCanvasView.insertSAMMImage(image, false);
							updateButtonsState();
						}
					});
				}
			} catch (IOException e) {
				Toast.makeText(DrawActivity.this, e.getMessage(),
						Toast.LENGTH_SHORT).show();
			}
			return null;
		}

		@Override
		protected void onPostExecute(final Void result) {
			mProgressDialog.dismiss();
		}
	}

	/**
	 * Creates an S Pen image based on a given bitmap.
	 * 
	 * @param bitmap
	 *            Bitmap to be loaded to an image
	 * @param compression
	 *            True if the given bitmap has to be compressed to a file first,
	 *            false otherwise
	 * @param scaleToCanvas
	 *            True if the given bitmap has to be scaled to the canvas size
	 *            (background), false if it has centered (external image)
	 * @return Created image object
	 * @throws IOException
	 *             When bitmap compression failed
	 */
	private SObjectImage getImageFromBitmap(final Bitmap bitmap,
			final boolean compression, final boolean scaleToCanvas)
			throws IOException {
		int imageWidth = bitmap.getWidth();
		int imageHeight = bitmap.getHeight();
		final SObjectImage image = new SObjectImage();
		RectF rect;
		int canvasWidth = sCanvasView.getWidth();
		int canvasHeight = sCanvasView.getHeight();
		if (scaleToCanvas) {
			image.putExtra(IMAGE_SCALED_TO_BACKGROUND, true);
			if (imageWidth > imageHeight) {
				int shift = canvasHeight - imageHeight * canvasWidth
						/ imageWidth;
				rect = new RectF(0, shift / 2, canvasWidth, canvasHeight
						- shift / 2);
			} else {
				int shift = canvasWidth - imageWidth * canvasHeight
						/ imageHeight;
				rect = new RectF(shift / 2, 0, canvasWidth - shift / 2,
						canvasHeight);
			}
		} else {
			image.putExtra(IMAGE_SCALED_TO_BACKGROUND, false);
			rect = new RectF((canvasWidth - imageWidth) / 2,
					(canvasHeight - imageHeight) / 2,
					(canvasWidth - imageWidth) / 2 + imageWidth,
					(canvasHeight - imageHeight) / 2 + imageHeight);
		}
		image.setRect(rect);
		if (compression) {
			final File imageFile = compressBitmap(bitmap);
			image.setImagePath(imageFile.getAbsolutePath());
		} else {
			image.setImageBitmap(bitmap);
		}
		return image;
	}

	/**
	 * Compresses bitmap into a file.
	 * 
	 * @param bitmap
	 *            Bitmap to be compressed
	 * @return File with compressed bitmap
	 * @throws IOException
	 *             When writing to a file failed.
	 */
	private File compressBitmap(final Bitmap bitmap) throws IOException {
		File file = new File(getExternalFilesDir(null),
				GroupDetail.TMP_FILE_NAME);
		OutputStream output = null;
		try {
			output = new BufferedOutputStream(new FileOutputStream(file));
			bitmap.compress(COMPRESS_FORMAT, COMPRESS_QUALITY, output);
		} finally {
			if (output != null) {
				output.close();
			}
		}
		return file;
	}

	/**
	 * Gets bitmap from a file.
	 * 
	 * @param file
	 *            File to be processed
	 * @return Created bitmap
	 * @throws IOException
	 *             When getting the picture rotation failed.
	 */
	private Bitmap loadBitmapFromFile(final File file) throws IOException {
		Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
		int rotation = getPictureRotation(file);
		if (rotation != 0 && bitmap != null) {
			Matrix matrix = new Matrix();
			matrix.setRotate(rotation);
			return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
					bitmap.getHeight(), matrix, true);
		}
		return bitmap;
	}

	/**
	 * Returns a picture rotation based on an Exif tags.
	 * 
	 * @param file
	 *            Picture file to be analyzed
	 * @return Picture rotation (in degrees)
	 * @throws IOException
	 *             When reading Exif tags from a file failed.
	 */
	private int getPictureRotation(final File file) throws IOException {
		ExifInterface exif = new ExifInterface(file.getAbsolutePath());
		int rotation;
		switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
				ExifInterface.ORIENTATION_UNDEFINED)) {
		case ExifInterface.ORIENTATION_NORMAL:
			rotation = 0;
			break;
		case ExifInterface.ORIENTATION_ROTATE_90:
			rotation = 90;
			break;
		case ExifInterface.ORIENTATION_ROTATE_180:
			rotation = 180;
			break;
		case ExifInterface.ORIENTATION_ROTATE_270:
			rotation = 270;
			break;
		default:
			rotation = 0;
			break;
		}

		return rotation;
	}

	private File getSavedCanvasFile() {
		return new File(getExternalFilesDir(null), SAVED_CANVAS_FILE_NAME);
	}

	@Override
	protected void onActivityResult(final int requestCode,
			final int resultCode, final Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		switch (requestCode) {
		case GALLERY_REQUEST_CODE:
			if (resultCode == RESULT_OK) {
				Bitmap bitmap = (Bitmap) data
						.getParcelableExtra(GalleryActivity.GALLERY_RESULT_NAME);
				try {
					sCanvasView.insertSAMMImage(
							getImageFromBitmap(bitmap, false, false), true);
				} catch (IOException e) {
					Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT)
							.show();
				}
				break;
			}
		case 0:
			DrawActivity.this.finish();
		default:
			break;
		}
	}

	@Override
	public void onSaveInstanceState(final Bundle outState) {
		new CanvasSaver().execute();
	}

	/**
	 * Gets the bitmap with the current canvas content.
	 * 
	 * @return Bitmap with the picture visible on the bitmap, null if canvas is
	 *         not initialized.
	 */
	public static Bitmap getBitmap() {
		if (sCanvasView == null) {
			return null;
		}

		return sCanvasView.getBitmap(true);
	}

	private class CanvasSaver extends AsyncTask<Void, Void, Void> {
		@Override
		protected Void doInBackground(final Void... params) {
			if (!mIsSavingCanvas) {
				mIsSavingCanvas = true;
				OutputStream output = null;
				try {
					output = new BufferedOutputStream(new FileOutputStream(
							getSavedCanvasFile()));
					sCanvasView.getBitmap(true).compress(COMPRESS_FORMAT,
							COMPRESS_QUALITY, output);
				} catch (FileNotFoundException e) {
					Toast.makeText(DrawActivity.this, e.getMessage(),
							Toast.LENGTH_SHORT).show();
				} finally {
					if (output != null) {
						try {
							output.close();
						} catch (IOException e) {
							Toast.makeText(DrawActivity.this, e.getMessage(),
									Toast.LENGTH_SHORT).show();
						}
					}
				}
			}
			return null;
		}

		@Override
		protected void onPostExecute(final Void result) {
			mIsSavingCanvas = false;
		}
	}
}
